﻿Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.ComponentModel.Design.Serialization
Imports System.Globalization
Imports System.Resources
Imports System.Workflow.ComponentModel.Compiler

Namespace System.Workflow.ComponentModel
    Friend Class ComponentDispenser
        ' Methods
        Private Shared Sub AddComponents(ByVal components As Dictionary([Of] Type, Object), ByVal attribComponents As Object())
            Dim obj2 As Object
            For Each obj2 In attribComponents
                If Not components.ContainsKey(obj2.GetType) Then
                    components.Add(obj2.GetType, obj2)
                End If
            Next
        End Sub

        Friend Shared Function CreateActivityExecutors(ByVal activity As Activity) As ActivityExecutor()
            If (activity Is Nothing) Then
                Throw New ArgumentNullException("activity")
            End If
            Dim list As New List([Of] ActivityExecutor)
            If activity.SupportsSynchronization Then
                list.Add(New SynchronizationFilter)
            End If
            If activity.SupportsTransaction Then
                list.Add(New TransactedContextFilter)
            End If
            If TypeOf activity Is CompositeActivity Then
                If TypeOf activity Is ICompensatableActivity Then
                    list.Add(New CompensationHandlingFilter)
                End If
                list.Add(New FaultAndCancellationHandlingFilter)
                list.Add(New CompositeActivityExecutor([Of] CompositeActivity))
            Else
                list.Add(New ActivityExecutor([Of] Activity))
            End If
            Return list.ToArray
        End Function

        Private Shared Function CreateComponentInstance(ByVal typeName As String, ByVal referenceType As Type) As Object
            Dim obj2 As Object = Nothing
            Dim type As Type = Nothing
            Try 
                Dim name As String = typeName
                Dim num As Integer = typeName.LastIndexOf("]"c)
                If (num <> -1) Then
                    name = typeName.Substring(0, (num + 1))
                Else
                    Dim index As Integer = typeName.IndexOf(","c)
                    If (index <> -1) Then
                        name = typeName.Substring(0, index)
                    End If
                End If
                type = referenceType.Assembly.GetType(name, False)
            Catch obj1 As Object
            End Try
            If (type Is Nothing) Then
                Try 
                    type = Type.GetType(typeName, False)
                Catch obj3 As Object
                End Try
            End If
            Dim message As String = Nothing
            If (Not type Is Nothing) Then
                Try 
                    obj2 = Activator.CreateInstance(type)
                Catch exception As Exception
                    message = exception.Message
                End Try
            End If
            If (Not obj2 Is Nothing) Then
                Return obj2
            End If
            Dim manager As New ResourceManager("System.Workflow.ComponentModel.StringResources", GetType(Activity).Assembly)
            If (Not manager Is Nothing) Then
                message = String.Format(CultureInfo.CurrentCulture, manager.GetString("Error_CantCreateInstanceOfComponent"), New Object() { typeName, message })
            End If
            Throw New Exception(message)
        End Function

        Friend Shared Function CreateComponents(ByVal objectType As Type, ByVal componentTypeAttribute As Type) As Object()
            Dim components As New Dictionary([Of] Type, Object)
            Dim list As New ArrayList
            Dim list2 As New ArrayList
            Dim list3 As New ArrayList
            Dim list4 As New ArrayList
            ComponentDispenser.GetCustomAttributes(objectType, GetType(ActivityCodeGeneratorAttribute), True)
            ComponentDispenser.GetCustomAttributes(objectType, GetType(ActivityValidatorAttribute), True)
            ComponentDispenser.GetCustomAttributes(objectType, GetType(DesignerAttribute), True)
            ComponentDispenser.GetCustomAttributes(objectType, GetType(DesignerSerializerAttribute), True)
            If ((objectType.GetCustomAttributes(GetType(SupportsTransactionAttribute), True).Length > 0) AndAlso (componentTypeAttribute Is GetType(ActivityValidatorAttribute))) Then
                list.Add(New TransactionContextValidator)
            End If
            If ((objectType.GetCustomAttributes(GetType(SupportsSynchronizationAttribute), True).Length > 0) AndAlso (componentTypeAttribute Is GetType(ActivityValidatorAttribute))) Then
                list3.Add(New SynchronizationValidator)
            End If
            ComponentDispenser.AddComponents(components, list3.ToArray)
            ComponentDispenser.AddComponents(components, list.ToArray)
            ComponentDispenser.AddComponents(components, list4.ToArray)
            ComponentDispenser.AddComponents(components, list2.ToArray)
            Dim list5 As New ArrayList
            Dim type As Type
            For Each type In objectType.GetInterfaces
                list5.AddRange(ComponentDispenser.GetCustomAttributes(type, componentTypeAttribute, True))
            Next
            list5.AddRange(ComponentDispenser.GetCustomAttributes(objectType, componentTypeAttribute, True))
            Dim codeGeneratorTypeName As String = Nothing
            Dim attribute As Attribute
            For Each attribute In list5
                Dim type2 As Type = Nothing
                If (componentTypeAttribute Is GetType(ActivityCodeGeneratorAttribute)) Then
                    codeGeneratorTypeName = DirectCast(attribute, ActivityCodeGeneratorAttribute).CodeGeneratorTypeName
                    type2 = GetType(ActivityCodeGenerator)
                ElseIf (componentTypeAttribute Is GetType(ActivityValidatorAttribute)) Then
                    codeGeneratorTypeName = DirectCast(attribute, ActivityValidatorAttribute).ValidatorTypeName
                    type2 = GetType(Validator)
                End If
                Dim obj2 As Object = Nothing
                Try 
                    If Not String.IsNullOrEmpty(codeGeneratorTypeName) Then
                        obj2 = ComponentDispenser.CreateComponentInstance(codeGeneratorTypeName, objectType)
                    End If
                Catch obj1 As Object
                End Try
                If (((obj2 Is Nothing) OrElse (type2 Is Nothing)) OrElse Not type2.IsAssignableFrom(obj2.GetType)) Then
                    Throw New InvalidOperationException(SR.GetString("Error_InvalidAttribute", New Object() { componentTypeAttribute.Name, objectType.FullName }))
                End If
                If Not components.ContainsKey(obj2.GetType) Then
                    components.Add(obj2.GetType, obj2)
                End If
            Next
            Return New ArrayList(components.Values).ToArray
        End Function

        Private Shared Function GetCustomAttributes(ByVal objectType As Type, ByVal attributeType As Type, ByVal inherit As Boolean) As Object()
            Dim customAttributes As Object() = Nothing
            Try 
                If (attributeType Is Nothing) Then
                    Return objectType.GetCustomAttributes(inherit)
                End If
                customAttributes = objectType.GetCustomAttributes(attributeType, inherit)
            Catch exception As Exception
                Throw New InvalidOperationException(SR.GetString("Error_InvalidAttributes", New Object() { objectType.FullName }), exception)
            End Try
            Return customAttributes
        End Function

        Friend Shared Sub RegisterComponentExtenders(ByVal extendingType As Type, ByVal extenders As IExtenderProvider())
            Dim list As List([Of] IExtenderProvider) = Nothing
            If Not ComponentDispenser.componentExtenderMap.ContainsKey(extendingType) Then
                list = New List([Of] IExtenderProvider)
                ComponentDispenser.componentExtenderMap.Add(extendingType, list)
            Else
                list = ComponentDispenser.componentExtenderMap.Item(extendingType)
            End If
            list.AddRange(extenders)
        End Sub


        ' Properties
        Friend Shared ReadOnly Property Extenders As IList([Of] IExtenderProvider)
            Get
                Dim list As New List([Of] IExtenderProvider)
                Dim list2 As IList([Of] IExtenderProvider)
                For Each list2 In ComponentDispenser.componentExtenderMap.Values
                    list.AddRange(list2)
                Next
                Return list.AsReadOnly
            End Get
        End Property


        ' Fields
        Private Shared componentExtenderMap As IDictionary([Of] Type, List([Of] IExtenderProvider)) = New Dictionary([Of] Type, List([Of] IExtenderProvider))
    End Class
End Namespace

